package org.summerframework.component.security.oauth.qq;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import org.summerframework.component.httpclient.HttpClientUtil;
import org.summerframework.component.httpclient.HttpParam;
import org.summerframework.component.httpclient.HttpResult;
import org.summerframework.component.security.oauth.LoginType;
import org.summerframework.component.security.oauth.OAuthAppIdAndAppSecret;
import org.summerframework.component.security.oauth.OAuthResultCode;
import org.summerframework.component.security.oauth.exception.HttpClientException;
import org.summerframework.component.security.oauth.exception.JsonParsingException;
import org.summerframework.component.security.oauth.exception.OAuthException;
import org.summerframework.component.security.oauth.exception.WeCatException;
import org.summerframework.component.security.oauth.util.HttpClientFinshUtil;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class QQOAuthSupper implements QQOAuthInterceptor {
    //access_token
    private static final String accessTokenUrl = "https://graph.qq.com/oauth2.0/token";
    //获取openid
    private static final String openIdUrl = "https://graph.qq.com/oauth2.0/me";
    //获取个人信息
    private static final String userInfoUrl = "https://graph.qq.com/user/get_user_info";

    private final QQAppIdAndAppSecret qqAppIdAndAppSecret;

    public QQOAuthSupper(QQAppIdAndAppSecret qqAppIdAndAppSecret) {
        this.qqAppIdAndAppSecret = qqAppIdAndAppSecret;
    }

    @Override
    public QQUserInfo getResultInfo(QQAccessToken qqAccessToken) {
        HttpParam httpParam = new HttpParam();

        httpParam.setMethod(RequestMethod.POST);
        httpParam.setUrl(accessTokenUrl);
        httpParam.addParam("grant_type", qqAccessToken.getGrantType());
        httpParam.addParam("client_id", getOAuthInfo().getAppId());
        httpParam.addParam("client_secret", getOAuthInfo().getAppSecret());
        httpParam.addParam("code", qqAccessToken.getCode());
        httpParam.addParam("redirect_uri", qqAppIdAndAppSecret.getRedirectUri());

        QQUserInfo qqUserInfo = fillAccessIoken(httpParam);
        String openId = getOpenId(qqUserInfo.getAccessToken());
        qqUserInfo.setOpenid(openId);
        return qqUserInfo;
    }

    @SuppressWarnings("unused")
    protected String getOpenId(String token) {
        QQUserInfo qqUserInfo = null;
        HttpParam httpParam = new HttpParam();
        httpParam.setMethod(RequestMethod.POST);
        httpParam.setUrl(openIdUrl);
        httpParam.addParam("access_token", token);
        HttpResult result = HttpClientUtil.request(httpParam);
        if (!result.isSuccess()) {
            throw new HttpClientException(OAuthResultCode.ILLEGAL_ARGUMENT, "httpclient request error: " + result.getErrMsg());
        }
        try {
            String jsonp = result.getContext();
            String openid;

            //正则求取openid
            Matcher m = Pattern.compile("\"openid\"\\s*:\\s*\"(\\w+)\"").matcher(jsonp);
            if (m.find()) {
                openid = m.group(1);
                return openid;
            } else {
                //请求错误后抛出
                Matcher m1 = Pattern.compile("\"code\"\\s*:\\s*\"(\\w+)\",\"msg\"\\s*:\\s*\"(\\w+)\"").matcher(jsonp);
                if (m1.find()) {
                    Integer code = Integer.parseInt(m.group(1));
                    String msg = m.group(2);
                    throw new OAuthException(OAuthResultCode.ILLEGAL_ARGUMENT, code + " error:" + msg);
                }
            }
        } catch (Exception e) {
            throw new HttpClientException(OAuthResultCode.ILLEGAL_ARGUMENT, "httpclient request error: ", e);
        }
        return null;
    }

    @Override
    public QQUserInfo getInfo(QQUserInfo qqUserInfo) {
        HttpParam httpParam = new HttpParam();
        httpParam.setMethod(RequestMethod.POST);
        httpParam.setUrl(userInfoUrl);
        httpParam.addParam("access_token", qqUserInfo.getAccessToken());
        httpParam.addParam("oauth_consumer_key", getOAuthInfo().getAppId());
        httpParam.addParam("openid", qqUserInfo.getOpenid());

        JSONObject json = HttpClientFinshUtil.finsh(httpParam);
        /*if(json.containsKey("error")){
            Integer errcode = json.getInt("error");
            String errmsg = json.getString("error_description");
            throw new WeCatException( errcode +": " + errmsg);
        }*/
        //用户的信息
        Integer ret = json.getInteger("ret");
        if (ret != 0) {
            String msg = json.getString("msg");
            throw new WeCatException(OAuthResultCode.ILLEGAL_ARGUMENT, ret + ": " + msg);
        }
        String nickname = json.getString("nickname");
        String sex = json.getString("gender");
        String province = json.getString("province");
        String city = json.getString("city");
        String figureurl = json.getString("figureurl");
        String figureurl1 = json.getString("figureurl_1");
        String figureurl2 = json.getString("figureurl_2");
        String figureurlQQ1 = json.getString("figureurl_qq_1");
        //判断是否有figureurl_qq_2
        String figureurlQQ2 = null;
        if (json.containsKey("figureurl_qq_2")) {
            figureurlQQ2 = json.getString("figureurl_qq_2");
        }
        String isYellowVip = json.getString("is_yellow_vip");
        String vip = json.getString("vip");
        String yellowVipLevel = json.getString("yellow_vip_level");
        String level = json.getString("level");
        String isYellowYearVip = json.getString("is_yellow_year_vip");

        qqUserInfo.setNickname(nickname);
        qqUserInfo.setSex(sex);
        qqUserInfo.setProvince(province);
        qqUserInfo.setCity(city);
        qqUserInfo.setFigureurl(figureurl);
        qqUserInfo.setFigureurl1(figureurl1);
        qqUserInfo.setFigureurl2(figureurl2);
        qqUserInfo.setFigureurlQQ1(figureurlQQ1);
        qqUserInfo.setFigureurlQQ2(figureurlQQ2);
        qqUserInfo.setIsYellowVip(isYellowVip);
        qqUserInfo.setIsYellowYearVip(isYellowYearVip);
        qqUserInfo.setLevel(level);
        qqUserInfo.setVip(vip);
        qqUserInfo.setYellowVipLevel(yellowVipLevel);
        return qqUserInfo;
    }

    @Override
    public OAuthAppIdAndAppSecret getOAuthInfo() {
        return qqAppIdAndAppSecret;
    }

    private QQUserInfo fillAccessIoken(HttpParam httpParam) {
        QQUserInfo qqUserInfo = new QQUserInfo();

        try {
            HttpResult result = HttpClientUtil.request(httpParam);

            if (!result.isSuccess()) {
                throw new HttpClientException(OAuthResultCode.ILLEGAL_ARGUMENT, "httpclient request error: " + result.getErrMsg());
            }

            String str = result.getContext();

            if (str.contains("callback")) {
                //将callback(jsonp数据)解析为json数据
                str = str.split("\\(")[1].split("\\)")[0];

                //将数据转换成json数据
                JSONObject json = JSONObject.parseObject(str);

                if (json.containsKey("error")) {
                    Integer errcode = json.getInteger("error");
                    String errmsg = json.getString("error_description");
                    qqUserInfo.setErrcode(errcode);
                    qqUserInfo.setErrmsg(errmsg);
                    throw new WeCatException(OAuthResultCode.ILLEGAL_ARGUMENT, errcode + ": " + errmsg);
                }
            }

            String[] tokens = str.split("&");
            String accessToken = null;
            Integer expiresIn = null;
            String refreshToken = null;
            for (String token : tokens) {
                if (token.contains("access_token")) {
                    accessToken = token.split("=")[1];
                } else if (token.contains("expires_in")) {
                    expiresIn = Integer.parseInt(token.split("=")[1]);
                } else if (token.contains("refresh_token")) {
                    refreshToken = token.split("=")[1];
                }

            }
            qqUserInfo.setAccessToken(accessToken);
            qqUserInfo.setExpiresIn(expiresIn);
            qqUserInfo.setRefreshToken(refreshToken);
        } catch (JSONException e) {
            throw new JsonParsingException(OAuthResultCode.ILLEGAL_ARGUMENT, "json parsing error: ");
        } catch (Exception e) {
            throw new HttpClientException(OAuthResultCode.ILLEGAL_ARGUMENT, "httpclient request error: ", e);
        }

        return qqUserInfo;
    }

    @Override
    public QQAccessToken getAccessToken(String code) {
        return new QQAccessToken(code);
    }

    @Override
    public boolean supportsType(LoginType loginType) {
        return LoginType.QQ == loginType;
    }
}
